package me.helllp.book.netty.step10;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;

/**
 * 自定义协议的服务器
 * 
 * @author Administrator
 *
 */
public class NettyServer {

	private static final Log LOG = LogFactory.getLog(NettyServer.class);

	public void bind() throws Exception {
		// 配置服务端的NIO线程组
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		ServerBootstrap b = new ServerBootstrap();

		b.group(bossGroup, workerGroup)
			.channel(NioServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG, 100)
			.handler(new LoggingHandler(LogLevel.INFO))
			.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws IOException {
					//	继承自LengthFieldBasedFrameDecoder，自定义长度解码器，解决粘包问题
					ch.pipeline().addLast(new NettyMessageDecoder(1024 * 1024, 4, 4));
					//	包装 MarshallingEncoder 编码器，处理为对象
					ch.pipeline().addLast(new NettyMessageEncoder());
					//	Netty提供的超时检测
					ch.pipeline().addLast("readTimeoutHandler", new ReadTimeoutHandler(50));
					//	登录的认证，通过黑白名单
					ch.pipeline().addLast(new LoginAuthRespHandler());
					//	心跳检测机制
					ch.pipeline().addLast("HeartBeatHandler", new HeartBeatRespHandler());
				}
			});

		// 绑定端口，同步等待成功
		b.bind(NettyConstant.REMOTEIP, NettyConstant.PORT).sync();
		LOG.info("Netty server start ok : " + (NettyConstant.REMOTEIP + " : " + NettyConstant.PORT));
	}

	public static void main(String[] args) throws Exception {
		new NettyServer().bind();
	}
}